Skip to content

一文了解Text Embedding模型:从text2vec、openai-text embedding到m3e、bge

发表: at 04:50

第一部分 衡量文本向量表示效果的榜单:MTEB、C-MTEB

1.1 《MTEB: Massive Text Embedding Benchmark(海量文本嵌入基准)》

判断哪些文本嵌入模型效果较好,通常需要一个评估指标来进行比较,《MTEB: Massive Text Embedding Benchmark(海量文本嵌入基准)》就是一个海量文本嵌入模型的评估基准

榜单地址:https://huggingface.co/spaces/mteb/leaderboard 图片

1.2 中文海量文本embedding任务排行榜:C-MTEB

从Chinese Massive Text Embedding Benchmark中可以看到目前最新的针对中文海量文本embedding的各项任务的排行榜,针对不同的任务场景均有单独的排行榜。

任务榜单包括:

其中,在本地知识库任务中,主要是根据问题query的embedding表示到向量数据库中检索相似的本地知识文本片段。因此,该场景主要是Retrieval检索任务。检索任务榜单如下: 图片

目前检索任务榜单下效果最好的是bge系列的bge-large-zh模型,langchain-chatchat项目中默认的m3e-base也处于比较靠前的位置

第二部分 OpenAI的text-embedding模型:从ada-002到3-small/3-large

2.1 text-embedding-ada-002

2.1.1 模型简介

text-embedding-ada-002是OpenAI于2022年12月提供的一个embedding模型,但需要调用接口付费使用。其具有如下特点:

2.1.2 模型使用

以下是OpenAI官方文档中给出的用于文本搜索的代码实例

from openai.embeddings_utils import get_embedding, cosine_similarity


def search_reviews(df, product_description, n=3, pprint=True):
  embedding = get_embedding(product_description, model='text-embedding-ada-002')
  df['similarities'] = df.ada_embedding.apply(lambda x: cosine_similarity(x, embedding))
  res = df.sort_values('similarities', ascending=False).head(n)
  return res


res = search_reviews(df, 'delicious beans', n=3)

3.2.3 最新发布的text-embedding-3之small/large的缩短嵌入技术

2.3.1 OpenAI三大嵌入模型的嵌入维度对比

ada v2text-embedding-3-smalltext-embedding-3-large
Embedding size1536512153625610243072
Average MTEB score61.061.662.362.064.164.6

从上图可知,text-embedding-3-small/large这两个新嵌入模型允许开发者通过在 dimensions API 参数中传递嵌入而不丢失其概念表征属性,从而缩短嵌入(即从序列末尾删除一些数字)

  1. 例如在 MTEB 基准上,text-embedding-3-large 可以缩短为 256 的大小, 同时性能仍然优于未缩短的 text-embedding-ada-002 嵌入(大小为 1536)
  2. 当然,仍然可以使用最好的嵌入模型 text-embedding-3-large 并指定 dimensions API 参数的值为 1024,使得嵌入维数从 3072 开始缩短,牺牲一些准确度以换取更小的向量大小

2.3.2 Matryoshka Representation Learning

OpenAI 所使用的「缩短嵌入」方法,随后引起了研究者们的广泛注意,最终发现,这种方法和 2022 年 5 月的一篇论文所提出的「Matryoshka Representation Learning」方法是相同的(MRL 的一作 Aditya Kusupati 也评论道:OpenAI 在 v3 嵌入 API 中默认使用 MRL 用于检索和 RAG!其他模型和服务应该很快就会迎头赶上)

不同于常规的fix的embedding表征,Matryoshka representation learning提出了一个方法,生成的表征是按照x下标进行重要性排序的,所以在资源受限的环境,可以只使用前面top-k维表征就可以

如下所示,对于图片,考虑一组表示尺寸图片,对于输入数据图片中的数据点图片,其的目标是学习一个图片维表示向量图片,对于每一个图片,MRL的目标是让前图片维的表征向量图片独立地成为可转移的通用表征向量 图片

再比如,在ImageNet-1K上训练ResNet50,将224×224像素的图像嵌入d=2048表示向量,然后通过线性分类器在图片个标签中进行预测图片

  1. 对于MRL,选择图片作为嵌套维度 假设得到了一个带标签的数据集图片,其中图片是输入点,图片是所有图片图片的标签

  2. MRL采用标准的经验风险最小化方法,通过使用独立的线性分类器对每个嵌套维度图片进行多类分类损失优化,参数化为图片 之后,所有损失分别按各自的重要性图片进行适当缩放后,做最终聚合MRL optimizes the multi-class classification loss for each of the nested dimension m ∈M using standard empirical risk minimization using a separatelinear classifier, parameterized by W(m) ∈RL×m .

    All the losses are aggregated after scaling withtheir relative importance (cm ≥0)m∈M respectively 尽管只对图片嵌套维度进行优化,MRL仍能产生精确的表示,并对介于所选表示粒度之间的维度进行插值

第三部分 m3e模型

3.1 m3e模型简介

M3E是Moka Massive Mixed Embedding的简称,解释一下

其有多个版本,分为m3e-small、m3e-base、m3e-large,m3e GitHub地址:GitHub - wangyingdong/m3e-base,其

3.1.1 m3e与openai text-embedding-ada-002

以下是m3e的一些重大更新

2023.06.07,添加文本分类任务的评测结果,在 6 种文本分类数据集上,m3e-base 在 accuracy 上达到了 0.6157(至于m3e-large则是0.6231),超过了 openai-ada-002 的 0.5956 见下图s2s ACC那一列(其中s2s, 即 sentence to sentence ,代表了同质文本之间的嵌入能力,适用任务:文本相似度,重复问题检测,文本分类等) 图片

此外,m3e团队建议:

3.2 m3e模型微调

微调脚本:m3e是使用uniem脚本进行微调

from datasets import load_dataset

from uniem.finetuner import FineTuner

dataset = load_dataset('shibing624/nli_zh', 'STS-B')
# 指定训练的模型为 m3e-small
finetuner = FineTuner.from_pretrained('moka-ai/m3e-small', dataset=dataset)
finetuner.run(epochs=3)

4第四部分 bge模型:采用RetroMAE预训练算法

2023年8月2日,北京智源人工智能研究院发布的中英文语义向量模型BGE

以下是BGE的技术亮点

4.1 RetroMAE的预训练步骤

目前主流的语言模型的预训练任务都是token级别的,比如MLM或者Seq2Seq,但是这种训练任务难以让模型获得一个高质量的基于句子级别的句向量,这限制了语言模型在检索任务上的潜力。针对这个弊端,目前有两者针对检索模型的预训练策略

基于此,研究人员提出了RetraoMAE(*RetroMAE论文:**https://arxiv.org/abs/2205.12035*),它包括两个模块,其一是一个类似于BERT的编码器,用于生成句向量,其二是一个一层transformer的解码器,用于重建句子,如下图所示![图片](@assets/images/2025/04/images110.jpg)

4.1.1 编码Encoding

所谓编码,即Mask(EN)掉一小部分token然后通过BERT编码得到句子嵌入*sentence embedding*图片,具体步骤如下

  1. 给定一个句子输入X:Norwegian forest cat is a breed of dom-estic cat originating in northern Europe
  2. 随机Mask(EN)掉其中一小部分token后得到图片[M] forest cat is a breed of [M] cat originating in [M] Europe 这里通常会采用一定的mask比例(15%~30%),从而能保留句子原本大部分的信息
  3. 然后利用类似BERT的编码器图片对其进行编码,得到对应的的句子嵌入图片一般将[CLS]位置最后一层的隐状态作为句子嵌入」,如下公式所

图片

We apply a BERT like encoder with 12 layers and768 hidden-dimensions, which helps to capture thein-depth semantics of the sentence. Following the common practice, we select the [CLS] token’s finalhidden state as the sentence embedding.

4.1.2 解码Decoding

所谓解码,即Mask(DE)很大一部分token然后结合句子嵌入图片*sentence embedding*,让解码器重构原始句子

具体而言,即是联合以下两个部分,好让解码器在该两部分的基础上重构原始句子

由于在解码器部分采用了极其简单的网络结构跟非常激进的mask比例,从而使得解码任务变得极具挑战性,迫使encoder去生成高质量的句向量才能最终准确地完成原文本重建

4.1.3 增强解码Enhanced Decoding

前面提及的解码策略有一种缺陷,就是训练信号只来源于被mask掉的token,而且每个mask掉的token都是基于同一个上下文重建的。于是研究人员提出了一种新的解码方法:Enhanced Decoding,具体做法如下

a) 首先生成两个不同的输入流H1(query)跟H2(context)

图片

其中图片是句子嵌入,图片是标记嵌入(在这个地方没有标记被掩码),图片是位置嵌入相当于

图片是sentence embedding + Position embedding

图片为sentence embedding和token embedding + position embedding

b) 通过attention机制得到新的输出A

图片

这里的M是一个mask矩阵,第i个token所能看得到的其他token是通过抽样的方式决定的(当然要确保看不到自身token,而且都要看得见第一个token,也就是encoder所产出CLS句向量的信息)

其中一个和常规decoder不一样的地方是,H1作为Q,H2作为KV H1中的每个token embedding去H2中查找比较重要的上下文:包括

H2被采样到的 token,以及初始token embedding

都能看到[这里的初始embedding就是sentence embedding],至于对角线上的因代表的各自自身,故看不到

为方便大家更好、更快的理解,我再举个例子,比如:

图片

最后,再总结一下RetroMAE 预训练步骤图片

  1. (A)编码阶段:将输入进行一定比例的mask操作,并编码为句子嵌入(绿色矩形)(A) Encoding: the input is moderately masked and encoded as the sentence embedding (the green rectangle)

  2. (B)解码阶段:对输入使用很高比例的mask操作,并与句子嵌入连接以恢复被mask的部分(阴影符号)(B) Decoding: the input is aggressively masked, and joined with the sentence embedding to reconstruct the masked tokens (the shadowed tokens).

  3. (C)增强编码阶段:基于每行的句子嵌入和可见上下文来重建所有输入符号;主对角线位置填充为-∞(灰色,因为其代表自身,故不可见),可见上下文的位置填充为0(蓝色)(C) Enhanced encoding: all input tokens are reconstructed based on the sentence embedding and the visible context in each row (defined in Eq. 7); the main diagonal positions are filled with −∞ (grey), and positions for the visible context are filled with 0 (blue).

4.2 bge模型的微调

难负样本是一种广泛使用的提高句子嵌入质量的方法。可以按照以下方法挖掘难负样本

python -m FlagEmbedding.baai_general_embedding.finetune.hn_mine \
--model_name_or_path BAAI/bge-base-en-v1.5 \
--input_file toy_finetune_data.jsonl \
--output_file toy_finetune_data_minedHN.jsonl \
--range_for_sampling 2-200 \
--use_gpu_for_searching
python -m FlagEmbedding.baai_general_embedding.finetune.hn_mine \

--model_name_or_path BAAI/bge-base-en-v1.5 \
--input_file toy_finetune_data.jsonl \
--output_file toy_finetune_data_minedHN.jsonl \
--range_for_sampling 2-200 \
--use_gpu_for_searching

4.3 新一代通用语义向量模型BGE-M3

4.3.1 BGE-M3:多语言、多粒度、多功能

近日,智源发布了BGE家族新成员——通用语义向量模型BGE-M3(其开源仓库及技术报告、模型链接)

  1. 多语言Multi-Linguality 支持超过100种语言,具备领先的多语言、跨语言检索能力

    具体而言,BGE-M3训练集包含100+种以上语言,既包含每种语言内部的语义匹配任务(Language X to Language X),又包含不同语言之间的语义匹配任务(Language X to Language Y) 丰富且优质的训练数据帮助BGE-M3建立了出色的多语言检索(Multi-Lingual Retrieval)与跨语言检索能力(Cross-Lingual Retrieval)

  2. 多粒度Multi-Granularity 全面且高质量地支撑“句子”、“段落”、“篇章”、“文档”等不同粒度的输入文本,最大输入长度为 8192

具体而言,BGE-M3目前可以处理最大长度为8192 的输入文本,极大地满足了社区对于长文档检索的需求。在训练BGE-M3时,智源研究员在现有长文本检索数据集的基础之上,通过模型合成的方式获取了大量文本长度分布多样化的训练数据 与此同时,BGE-M3通过改进分批(batch)与缓存(cache)策略,使得训练过程具备足够高的吞吐量与负样本规模,从而确保了训练结果的质量。基于数据与算法双层面的优化处理,BGE-M3得以高质量的支持“句子”、“段落”、“篇章”、“文档”等不同粒度的输入文本

  1. 多功能Multi-Functionality 一站式集成了稠密检索、稀疏检索、多向量检索三种检索功能

具体而言,不同于传统的语义向量模型,BGE-M3既可以借助特殊token [CLS]的输出向量用以来完成稠密检索(Dense Retrieval)任务 又可以利用其他一般性token的输出向量用以支持稀疏检索(Sparse Retrieval)与多向量检索(Multi-vector Retrieval)

三种检索功能的高度集成使得BGE-M3可以一站式服务不同的现实场景,如语义搜索、关键字搜索、重排序 同时,无需使用多个模型进行多个推理,BGE-M3一次推理就可以得到多个不同模式的输出,无需额外开销,并能高效支持混合检索,联合三种检索模式可获得更加精准的检索结果

4.3.2 训练数据

在训练数据上,包括

  1. 未标记语料库的弱监督数据 通过提取Wikipedia、S2ORC、xP3、mC4和CC-News等各种多语言语料库中的丰富语义结构(如标题-正文、标题-摘要、指令-输出等)来进行整理 为了学习用于跨语言语义匹配的统一嵌入空间,从两个翻译数据集MTP、NLLB中进行处理,总共收集了194种语言的12亿个文本对和2655个跨语言对应

  2. 标记语料库的微调数据 对于英语,包括八个数据集,包括HotpotQA、TriviaQA、NQ、MSMARCO、COLIEE、PubMedQA以及SimCSE收集的NLI数据 对于中文,包括七个数据集,包括DuReader、mMARCO-ZH、T2-Ranking、LawGPT1、CmedQAv2和LeCaRDv2 对于其他语言,利用来自MIRACL的训练数据

合成的多语言微调数据 另外,为了缓解长文档检索任务的性能,通过生成合成数据方式进行处理,并引入额外的多语言微调数据(记为MultiLongDoc) 具体实现时,从Wiki和MC4数据集中抽取长篇文章,并从中随机选择段落。然后,使用GPT-3.5根据这些段落生成问题,生成的问题和抽样文章构成微调数据的新文本对 这里采用的prompt为:

“You are a curious AI assistant, please generate one specific and valuable question based on the following text. The generated question should revolve around the core content of this text, and avoid using pronouns (e.g., ”this”). Note that you should generate only one question, without including additional content:”

最终得到的数据分布如下:图片

4.3.3 混合检索与模型训练

如BGE模型一致,BGE-M3模型训练分为三个阶段:

4.3.3.1 混合检索

M3-Embedding统一了嵌入模型的所有三种常见检索功能,即稠密检索、词性(稀疏)检索和多向量检索

sdense,密集检索

可以根据文本编码器将输入查询q转换成隐藏状态图片,继而

→使用特殊标记”[CLS]“的归一化隐藏状态来表示查询q的嵌入:图片

→使用图片来表示段落p的嵌入

故,查询和段落之间的相关性得分是通过两个嵌入式eq和ep之间的内积来衡量:图片

其中图片是将隐藏状态映射到浮点数的矩阵 如果一个术语t在查询中出现多次,只保留其最大权重,用同样的方法计算段落中每个术语的权重 在估算术语权重的基础上,查询和段落之间的相关性得分由查询和段落中共存术语(表示为图片,也就是交集)的联合重要性计算得出(Based on the estimation term weights, the relevance score between query and passage is computed by the joint importance of the co-existed terms (denoted as q ∩ p) with in the query and passage):

图片

最后,由于嵌入模型的多功能性,检索过程可以采用混合过程

  1. 首先,候选结果可以由每种方法单独检索(多向量方法由于成本高,可以免去这一步骤)

  2. 然后,根据综合相关性得分对最终检索结果重新排序:srank←sdense+slex+smul

4.3.3.2 模型训练

嵌入模型经过训练,可以区分正样本和负样本。对于每一种检索方法,它都有望为查询的正样本分配一个更高的分数,因此,进行训练过程是为了最小化In-foNCE损失,如下表示

图片

其中

在知识蒸馏阶段,以总得分sinter为教师模型监督信号,其中的任何一个得分作为学生模型

将每种检索方法的损失函数修改为:

图片

进一步对修正后的损失函数进行积分和归一化处理:

图片

最后使用线性组合推导出自我知识蒸馏的最终损失函数

图片

整个训练过程是一个两阶段的工作流程,如下所示: 首先,使用弱监督数据对文本编码器进行预训练,其中只有密集检索是以对比学习的基本形式进行训练的 其次,自我知识蒸馏应用于第二阶段,在此阶段对嵌入模型进行微调,以建立三种检索功能。在这一阶段中,将使用标注数据和合成数据,并根据ANCE方法为每个查询引入硬负样本

4.3.4 三大关键技术:自学习蒸馏、训练效率优化、长文本优化等

由于引入了大量文本长度差异极大的训练数据,常规的对比学习训练方法的效率非常低下 一方面,长文本会消耗相当多的显存,大大的限制了训练时的batch size 其次,短文本不得不填充至更长的长度以对齐同一批次的长文本,这样就引入了大量无意义的计算 此外,训练数据的长度差异容易使得不同GPU之间的计算负荷分布不均并引发相互等待,造成不必要的训练延时

为了解决这些问题,我们优化了训练流程,如下图所示图片

→首先,根据长度对文本数据进行分组,并从每组中采样数据,确保一个batch内文本长度相对相似,从而减少填充。同时,数据程序会首先从组内采样足够的数据,然后分配给各机器,保证不同机器的计算开销尽可能相近

→为了减少文本建模时的显存消耗,我们将一批数据分成多个小批。对于每个小批,我们利用模型编码文本,收集输出的向量同时丢弃所有前向传播中的中间状态,最后汇总向量计算损失。通过这种方式,可以显著增加训练的batch size(且当建模长文本或者向量模型很大时,都可以采用此来扩大batch size)

长文本优化

目前,开源社区缺少用于文档级检索的开源数据集。为此,我们借助大语言模型生产了一份包括13种语言的长文档检索数据。另外,由于缺乏长文本数据或计算资源,实际情况下长文本微调不一定可以进行 在这种情况下,我们提出了一种简单而有效的方法:MCLS(Multiple CLS)来增强模型的能力,而无需对长文本进行微调,如下图所示

图片


上篇文章
5部场面宏大的海战电影,震撼场景燃爆你的屏幕
下篇文章
谷歌 A2A (Agent2Agent)架构设计深度剖析